import { Ref, set } from 'vue'
import { Widget } from '@/models'
import useDocScroll from './useDocScroll'
import useWidgetActive from './useWidgetActive'

/** 控件操作 */
export default function useWidgetOperate(
  widgets: Ref<Widget[]>,

  emit: ((event: 'widget-add', widget: Widget) => void) & ((event: 'widget-remove', widget: Widget) => void),

  widgetActive: ReturnType<typeof useWidgetActive>,

  scrollToWidget: ReturnType<typeof useDocScroll>['scrollToWidget'],

  beforeWidgetRemove?: Ref<((...widgets: Widget[]) => void) | undefined>
) {
  /**
   * 通过 id 查找控件
   * @param {string} id
   */
  const findWidgetById = (id: string) => widgets.value.find(item => item.id === id)

  /** 添加控件 */
  function addWidget(...items: Widget[]) {
    const list = widgets.value

    items.forEach(widget => {
      /** 骑缝控件 */
      if (widget.isRiding) {
        // 相同文档、相同参与方的骑缝控件索引
        const idx = list.findIndex(
          item =>
            item.isRiding &&
            item.type === widget.type &&
            item.actor.id === widget.actor.id &&
            item.docId === widget.docId
        )

        if (idx > -1) {
          // 删除匹配到的骑缝控件
          list.splice(idx, 1)
        }
      }

      list.push(widget)

      emit('widget-add', widget)
    })
  }

  /**
   * 删除控件
   * @param {(Widget | string)} widget 控件或控件 id
   * @param {boolean} direct 是否直接删除，否则将触发 `beforeWidgetRemove`，默认 `true`
   * @param {boolean} link 是否删除关联控件，默认 `false`
   */
  async function removeWidget(widget?: Widget | string, direct = true, link = false) {
    const list = widgets.value

    if (typeof widget === 'string') {
      widget = findWidgetById(widget)
    }

    if (!widget) return

    const idx = list.indexOf(widget)

    if (idx < 0) return

    if (!direct) {
      await beforeWidgetRemove?.value?.(widget)
    }

    list.splice(idx, 1)

    emit('widget-remove', widget)

    const { linkId } = widget

    if (link && linkId) {
      // 同步删除批量关联控件
      removeWidgets(widget.linkWidgets)
    }
  }

  /**
   * 删除多个控件
   * @param {(Widget | string)[]} widgets 控件或控件 id 列表
   * @param {boolean} direct 是否直接删除，否则将触发 `beforeWidgetRemove`，默认 `true`
   * @param {boolean} link 是否删除关联控件，默认 `false`
   */
  async function removeWidgets(items: (Widget | string)[], direct = true, link = false) {
    /** 将要删除的控件 */
    const removes = items
      .map(widget => (typeof widget !== 'string' ? widget : findWidgetById(widget)))
      .filter(widget => !!widget) as Widget[]

    if (!removes.length) return

    if (!direct) {
      await beforeWidgetRemove?.value?.(...removes)
    }

    removes.forEach(widget => removeWidget(widget, true, link))
  }

  /**
   * 聚焦控件
   * @param {string} id 控件 id
   * @param {boolean} focusInput 是否聚焦 input
   * @param {boolean} page 控件所在页面，骑缝或批量控件可能需要跳转对应页面
   */
  async function focusWidget(id: string, focusInput = true, page?: number) {
    await scrollToWidget(id, page)

    widgetActive.activeWidgetId = id

    if (focusInput) {
      const widgetSelector = `.fa-contract [widget-id="${id}"]`
      const input = document.querySelector(
        `${widgetSelector} input, ${widgetSelector} textarea`
      ) as HTMLInputElement | null

      input?.focus()
    }
  }

  return {
    /** 通过 id 查找控件 */
    findWidgetById,

    /** 添加控件 */
    addWidget,

    /** 删除控件 */
    removeWidget,

    /** 删除多个控件 */
    removeWidgets,

    /** 聚焦控件 */
    focusWidget
  }
}
